#include "stdafx.h"

#include <MyControls/SelectTool.h>
#include <MyControls/BezierEditor.h>

namespace My {

// SelectTool

SelectTool::SelectTool(BezierEditor & owner)
	: m_Owner(owner)
{
	m_Hit.code = htNone;
}

void SelectTool::Activate()
{
}

void SelectTool::Deactivate()
{
	m_Hit.code = htNone;
}

void SelectTool::PaintRect(CDC * pDC, const CRect & r)
{
}

void SelectTool::OnLButtonDown(UINT nFlags, CPoint p)
{
	if (m_Owner.ControlPointAt(p, m_Hit.curve, m_Hit.node, m_Hit.control)) {
		m_Hit.code = htControlPoint;
		return;
	}
	if (m_Owner.NodeAt(p, m_Hit.curve, m_Hit.node)) {
		m_Hit.code = htNode;
		Bezier & b = m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve);
		m_Hit.select = !b.IsSelected(m_Hit.node);
		if (m_Hit.select) {
			if ((GetAsyncKeyState(VK_SHIFT) & (~0 << 1)) == 0)
				m_Owner.GetBezierOwner()->DeselectAll();
			if ((GetAsyncKeyState(VK_MENU) & (~0 << 1)) == 0)
				b.Select(m_Hit.node);
			else
				b.Select();
		}
		return;
	}
	if (m_Owner.CurveAt(p, m_Hit.curve, m_Hit.t)) {
		m_Hit.code = htCurve;
		Bezier & b = m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve);
		Size i = Size(floor(m_Hit.t));
		m_Hit.select = !b.IsSelected(i) || !b.IsSelected(Next(b, i));
		if (m_Hit.select) {
			if ((GetAsyncKeyState(VK_SHIFT) & (~0 << 1)) == 0)
				m_Owner.GetBezierOwner()->DeselectAll();
			if ((GetAsyncKeyState(VK_MENU) & (~0 << 1)) == 0) {
				b.Select(i);
				b.Select(Next(b, i));
			} else
				b.Select();
		}
		return;
	}
	m_Hit.code = htRange;
}

void SelectTool::OnLButtonDblClk(UINT nFlags, CPoint p)
{
}

void SelectTool::OnLButtonUp(UINT nFlags, CPoint p)
{
	switch (m_Hit.code) {
	case htNode:
		if (!m_Hit.select && (GetAsyncKeyState(VK_SHIFT) & (~0 << 1)) != 0) {
			Bezier & b = m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve);
			b.Deselect(m_Hit.node);
		}
		break;
	case htCurve:
		if (!m_Hit.select && (GetAsyncKeyState(VK_SHIFT) & (~0 << 1)) != 0) {
			Bezier & b = m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve);
			Size i = Size(floor(m_Hit.t));
			b.Deselect(i);
			b.Deselect(Next(b, i));
		}
		break;
	case htRange:
	case htNone:
		if ((GetAsyncKeyState(VK_SHIFT) & (~0 << 1)) == 0)
			m_Owner.GetBezierOwner()->DeselectAll();
		break;
	}
	m_Hit.code = htNone;
}

void SelectTool::OnRButtonDown(UINT nFlags, CPoint p)
{
}

void SelectTool::OnRButtonDblClk(UINT nFlags, CPoint p)
{
}

void SelectTool::OnRButtonUp(UINT nFlags, CPoint p)
{
}

void SelectTool::OnMouseMove(UINT nFlags, CPoint p)
{
	switch (m_Hit.code) {
	case htControlPoint:
		m_Owner.GetBench().SetManipulator(
			std::auto_ptr<Manipulator>(new DragControlPoint(
			m_Owner,
			m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve),
			Size(m_Hit.node), 
			Size(m_Hit.control),
			p)));
		m_Hit.code = htNone;
		break;
	case htNode:
		m_Owner.GetBench().SetManipulator(
			std::auto_ptr<Manipulator>(new DragNodes(m_Owner, p)));
		m_Hit.code = htNone;
		break;
	case htCurve:
		m_Owner.GetBench().SetManipulator(
			std::auto_ptr<Manipulator>(new DragCurve(m_Owner, 
			m_Owner.GetBezierOwner()->GetBezier(m_Hit.curve),
			m_Hit.t, p)));
		m_Hit.code = htNone;
		break;
	case htRange:
		m_Owner.GetBench().SetManipulator(
			std::auto_ptr<Manipulator>(new SelectRange(m_Owner, p)));
		m_Hit.code = htNone;
		break;
	}
}

void SelectTool::OnMouseEnter(UINT nFlags, CPoint p)
{
}

void SelectTool::OnMouseLeave()
{
}

void SelectTool::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
}

void SelectTool::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
}

bool SelectTool::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	CPoint p;
	GetCursorPos(&p);
	m_Owner.GetBench().ScreenToClient(&p);

	if (m_Owner.ControlPointAt(p, m_Hit.curve, m_Hit.node, m_Hit.control) 
		|| m_Owner.NodeAt(p, m_Hit.curve, m_Hit.node)
		|| m_Owner.CurveAt(p, m_Hit.curve, m_Hit.t)) 
	{
		SetCursor(GetApp().LoadCursor("CURSOR_EDIT"));
		return true;
	} else
		return false;
}

} //namespace My
